package cn.baiweigang.uu.service;

import cn.baiweigang.uu.constants.BtcConfig;
import cn.baiweigang.uu.db.AccountInfoDb;
import cn.baiweigang.uu.db.BalanceHistoryDb;
import cn.baiweigang.uu.db.OrderHistoryDb;
import cn.baiweigang.uu.db.SummarySheetDb;
import cn.baiweigang.uu.enums.ContractCodeEnum;
import cn.baiweigang.uu.enums.MarginModeEnum;
import cn.baiweigang.uu.enums.PeriodEnum;
import cn.baiweigang.uu.enums.SymbolEnum;
import cn.baiweigang.uu.model.AccountInfo;
import cn.baiweigang.uu.model.DataMap;
import cn.baiweigang.uu.model.StrategyInfo;
import cn.baiweigang.uu.model.SummarySheetInfo;
import cn.baiweigang.uu.utils.DateUtil;
import cn.baiweigang.uu.utils.LogUtil;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class DbService {

    public void insertBalanceHistoryForDay1(AccountInfo accountInfo) {
        Map<String, String> map = new HashMap<>();
        map.put("balance", accountInfo.getMarginBalance().doubleValue() + "");
        //计算收益率
        double preDayBalance = 0;
        DataMap dataMap = BalanceHistoryDb.queryByPeriodAndDateTime(accountInfo, PeriodEnum.DAY1,
                DateUtil.formatDateYMD(DateUtil.addDays(new Date(), -1)));
        if (dataMap != null) {
            preDayBalance = dataMap.getDoubleValue("balance");
        }
        if (preDayBalance > 0) {
            double profitRate = (accountInfo.getMarginBalance().doubleValue() - preDayBalance) * 100 / preDayBalance;
            map.put("profit_rate", profitRate + "");
        }
        BalanceHistoryDb.inster(accountInfo, PeriodEnum.DAY1, DateUtil.formatDateYMD(), map);
    }

    /**
     * 把已成交的订单信息 写入DB
     *
     * @param strategyInfo
     */
    public void insertOrderHistory(StrategyInfo strategyInfo) {
        LogUtil.logInfo("已平仓的订单 写入DB");
        OrderHistoryDb.insert(strategyInfo);

        //汇总当天订单信息
        LogUtil.logInfo("有订单成交，汇总当天订单信息");
        insertSummarySheetForDay1(strategyInfo.getAccountInfo());
    }

    /**
     * 统计指定日期 按天汇总
     *
     * @param accountInfo
     */
    public void insertSummarySheetForDay1(AccountInfo accountInfo) {
        //先查出当天所有订单信息
        String toDateTime = DateUtil.formatDateYMD(DateUtil.addDays(new Date(), 1));
        List<DataMap> dataMapList = OrderHistoryDb.queryAllByCloseGmt(accountInfo, DateUtil.formatDateYMD(), toDateTime);
        //汇总数据
        double tp = 0;
        double sl = 0;
        double tpVolume = 0;
        double slVolume = 0;
        double fee = 0;
        int tpOrderNum = 0;
        int slOrderNum = 0;
        int holdMinutes = 0;
        for (DataMap dataMap : dataMapList) {
            if (dataMap.getDoubleValue("profit_volume") > 0) {
                tp += dataMap.getDoubleValue("profit");
                tpVolume += dataMap.getDoubleValue("profit_volume");
                tpOrderNum++;
            } else {
                sl += dataMap.getDoubleValue("profit");
                slVolume += dataMap.getDoubleValue("profit_volume");
                slOrderNum++;
            }
            fee += dataMap.getDoubleValue("fee");
            holdMinutes += dataMap.getIntValue("hold_minutes");
        }
        Map<String, String> map = new HashMap<>();
        map.put("profit", tp + sl + "");
        map.put("tp", tp + "");
        map.put("sl", sl + "");
        map.put("profit_volume", tpVolume + slVolume + "");
        map.put("tp_volume", tpVolume + "");
        map.put("sl_volume", slVolume + "");
        map.put("fee", fee + "");
        map.put("order_num", tpOrderNum + slOrderNum + "");
        map.put("tp_order_num", tpOrderNum + "");
        map.put("sl_order_num", slOrderNum + "");
        if (tpOrderNum + slOrderNum > 0) {
            map.put("avg_hold_minutes", holdMinutes / (tpOrderNum + slOrderNum) + "");
        }
        if (tpOrderNum > 0) {
            map.put("tp_avg_volume", tpVolume / tpOrderNum + "");
        }
        if (slOrderNum > 0) {
            map.put("sl_avg_volume", slVolume / slOrderNum + "");
        }
        SummarySheetDb.inster(accountInfo, PeriodEnum.DAY1, DateUtil.formatDateYMD(), map);
    }

    public SummarySheetInfo queryDay1(AccountInfo accountInfo, String dateTime) {
        DataMap dataMap = SummarySheetDb.queryByPeriodAndDateTime(accountInfo, PeriodEnum.DAY1, dateTime);
        if (dataMap == null) return null;
        SummarySheetInfo summarySheetInfo = new SummarySheetInfo();
        summarySheetInfo.setAccountName(dataMap.getStringValue("account_name"));
        summarySheetInfo.setContractCode(ContractCodeEnum.byCode(dataMap.getStringValue("contract_code")));
        summarySheetInfo.setPeriod(PeriodEnum.DAY1);
        summarySheetInfo.setDateTime(dataMap.getStringValue("date_time"));
        summarySheetInfo.setProfit(dataMap.getDoubleValue("profit"));
        summarySheetInfo.setTp(dataMap.getDoubleValue("tp"));
        summarySheetInfo.setSl(dataMap.getDoubleValue("sl"));
        summarySheetInfo.setProfitVolume(dataMap.getDoubleValue("profit_volume"));
        summarySheetInfo.setTpVolume(dataMap.getDoubleValue("tp_volume"));
        summarySheetInfo.setSlVolume(dataMap.getDoubleValue("sl_volume"));
        summarySheetInfo.setFee(dataMap.getDoubleValue("fee"));
        summarySheetInfo.setOrderNum(dataMap.getIntValue("order_num"));
        summarySheetInfo.setOrderNum(dataMap.getIntValue("tp_order_num"));
        summarySheetInfo.setOrderNum(dataMap.getIntValue("sl_order_num"));
        summarySheetInfo.setTpAvgVolume(dataMap.getDoubleValue("tp_avg_volume"));
        summarySheetInfo.setSlAvgVolume(dataMap.getDoubleValue("sl_avg_volume"));
        return summarySheetInfo;
    }

    /**
     * 最近10笔 亏损订单数
     *
     * @param accountInfo
     * @return
     */
    public int queryAlwaysSlNum(AccountInfo accountInfo) {
        List<DataMap> dataMapList = OrderHistoryDb.queryLast(accountInfo, 10);
        int num = 0;
        if (dataMapList != null && dataMapList.size() > 0) {
            for (DataMap dataMap : dataMapList) {
                if (dataMap.getDoubleValue("profit_volume") < 0) {
                    num++;
                } else {
                    break;
                }
            }
        }
        return num;
    }

    /**
     * 根据账号名 从DB读取账户信息
     *
     * @param accountName
     * @return
     */
    public AccountInfo queryFromDb(String accountName) {
        DataMap dataMap = AccountInfoDb.query(accountName);
        return convert2(dataMap);
    }

    private AccountInfo convert2(DataMap dataMap) {
        if (dataMap == null) return null;
        AccountInfo accountInfo = new AccountInfo();
        accountInfo.setAccountName(dataMap.getStringValue("account_name"));
        accountInfo.setSymbol(SymbolEnum.byCode(dataMap.getStringValue("symbol")));
        accountInfo.setContractCode(ContractCodeEnum.byCode(dataMap.getStringValue("contract_code")));
        accountInfo.setMarginMode(MarginModeEnum.byCode(dataMap.getStringValue("margin_mode")));
        accountInfo.setForcedCloseUsd(dataMap.getDoubleValue("forced_close_usd"));
        accountInfo.setOpenVolume(dataMap.getLongValue("min_volume"));
        accountInfo.setMaxVolume(dataMap.getLongValue("max_volume"));
        accountInfo.setContractSize(new BigDecimal(dataMap.getStringValue("contract_size")));
        accountInfo.setPriceTick(new BigDecimal(dataMap.getStringValue("price_tick")));
        accountInfo.setStrategyName(dataMap.getStringValue("strategy_name"));
        accountInfo.setAvailable("1".equals(dataMap.getStringValue("status")));
        accountInfo.setPeriod(PeriodEnum.valueOf(dataMap.getStringValue("period")));
        //把key加载到内存中
        BtcConfig.setApiKey(accountInfo.getAccountName(), dataMap.getStringValue("api_key"),
                dataMap.getStringValue("secret_key"));
        return accountInfo;
    }
}
